package com.plian.system.service.fr.procurement.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.plian.Tools.CollectionUtil;
import com.plian.Tools.StringPool;
import com.plian.Tools.StringUtil;
import com.plian.Tools.file.FilesUtil;
import com.plian.Tools.pagedata.PageData;
import com.plian.system.constant.yth.YthConstant;
import com.plian.system.dao.sys.file.FileDao;
import com.plian.system.dto.fr.procurement.PurchaseTransferFileDTO;
import com.plian.system.entity.fr.procurement.MaterialProcurement;
import com.plian.system.entity.fr.procurement.ProcurementContract;
import com.plian.system.entity.pm.property.PropertyBasics;
import com.plian.system.entity.sys.Org;
import com.plian.system.properties.GzwProperties;
import com.plian.system.service.fr.procurement.IMaterialProcurementService;
import com.plian.system.service.fr.procurement.IProcurementContractService;
import com.plian.system.service.fr.procurement.IPurchaseTransferService;
import com.plian.system.service.pm.property.IPropertyBasicsService;
import com.plian.system.service.sys.code.IFormCodeService;
import com.plian.system.service.sys.file.FileService;
import com.plian.system.service.sys.orgzation.IOrgService;
import com.plian.system.vo.fr.procurement.PurchaseTransferResultVO;
import com.plian.system.vo.yth.YthResult;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.plian.system.constant.sys.FormTypeConstant.FR_MATERIAL_PROCUREMENT_FORM;
/**
 * @description:
 * @author: gangan
 * @create: 2022-04-21 16:33
 */
@Slf4j
@Service
@AllArgsConstructor
public class PurchaseTransferServiceImpl implements IPurchaseTransferService {

    private IMaterialProcurementService materialProcurementService;

    private IProcurementContractService procurementContractService;

    private IFormCodeService formCodeService;

    private FileService fileService;

    private FileDao fileDao;

    private IPropertyBasicsService propertyBasicsService;

    private GzwProperties gzwProperties;

    private IOrgService orgService;

    /**
     * 阳光采购类型
     */
    final private static String SUN_DATA_SOURCE = "1";

    final private static Integer FINISH = 3;

    final private static Integer INIT_DELETED = 0;

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public PurchaseTransferResultVO saveList(List<MaterialProcurement> materialProcurementList) {
        List<MaterialProcurement> existList = materialProcurementService
                        .list(new LambdaQueryWrapper<MaterialProcurement>()
                        .eq(MaterialProcurement::getDataSource, SUN_DATA_SOURCE)
                        .isNotNull(MaterialProcurement::getDataSourceId));
        Map<String, MaterialProcurement> existMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(existList)){
            existMap = existList.stream().collect(Collectors
                    .toMap(MaterialProcurement::getDataSourceId, materialProcurement -> materialProcurement));
        }

        List<ProcurementContract> existContractList = procurementContractService
                .list(new LambdaQueryWrapper<ProcurementContract>()
                        .eq(ProcurementContract::getDataSource, SUN_DATA_SOURCE)
                        .isNotNull(ProcurementContract::getDataSourceId));
        Map<String, ProcurementContract> existContractMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(existContractList)){
            existContractMap = existContractList.stream().collect(Collectors
                    .toMap(ProcurementContract::getDataSourceId, procurementContract -> procurementContract));
        }

        List<Long> existIds = new ArrayList<>();
        materialProcurementList = materialProcurementList.stream()
                .filter(materialProcurement -> StringUtil.isNotBlank(materialProcurement.getDataSourceId())).collect(Collectors.toList());
        List<String> insertIds = new ArrayList<>();
        List<String> updateIds = new ArrayList<>();

        List<PropertyBasics> propertyBasicsList = propertyBasicsService
                .list(new LambdaQueryWrapper<PropertyBasics>().ne(PropertyBasics::getStatus, 4)
                        .eq(PropertyBasics::getCompetentOrganization, gzwProperties.getId()).isNotNull(PropertyBasics::getOrgCode));
        Map<String, PropertyBasics> propertyMap = propertyBasicsList.stream()
                .collect(Collectors.toMap(PropertyBasics::getOrgCode, propertyBasics -> propertyBasics));
        for (MaterialProcurement materialProcurement : materialProcurementList){
            if (existMap.containsKey(materialProcurement.getDataSourceId())){
                materialProcurement.setId(existMap.get(materialProcurement.getDataSourceId()).getId());
                existIds.add(materialProcurement.getId());
                updateIds.add(materialProcurement.getDataSourceId());
            }else {
                materialProcurement.setId(null);
                insertIds.add(materialProcurement.getDataSourceId());
            }
            materialProcurement.setFormType(String.valueOf(FR_MATERIAL_PROCUREMENT_FORM));
            if (StringUtil.isBlank(materialProcurement.getCode())){
                materialProcurement.setCode(formCodeService.getCode(Integer.valueOf(materialProcurement.getFormType())));
            }
            if (StringUtil.isNotBlank(materialProcurement.getFillingUnitId())
                    && propertyMap.containsKey(materialProcurement.getFillingUnitId())){
                materialProcurement.setFillingUnitId(propertyMap.get(materialProcurement.getFillingUnitId()).getOrgId());
            }
            if (StringUtil.isBlank(materialProcurement.getCreateCompanyId())){
                materialProcurement.setCreateCompanyId(materialProcurement.getFillingUnitId());
            }
            materialProcurement.setDataSource(SUN_DATA_SOURCE);
            materialProcurement.setStatus(FINISH);
            materialProcurement.setIsDeleted(INIT_DELETED);
        }

        materialProcurementService.saveOrUpdateBatch(materialProcurementList);

        List<ProcurementContract> procurementContractList = new ArrayList<>();
        List<ProcurementContract> contractRemoveList = new ArrayList<>();
        contractRemoveList.addAll(existContractList);
        for (MaterialProcurement materialProcurement : materialProcurementList){
            if (CollectionUtil.isNotEmpty(materialProcurement.getProcurementContracts())){
                for (ProcurementContract procurementContract : materialProcurement.getProcurementContracts()){
                    procurementContract.setMaterialProcurementId(materialProcurement.getId());
                    procurementContract.setDataSource(SUN_DATA_SOURCE);
                    procurementContract.setIsDeleted(INIT_DELETED);
                    if (existContractMap.containsKey(procurementContract.getDataSourceId())){
                        procurementContract.setId(existContractMap.get(procurementContract.getDataSourceId()).getId());
                        contractRemoveList.remove(existContractMap.get(procurementContract.getDataSourceId()));
                    }
                }
                procurementContractList.addAll(materialProcurement.getProcurementContracts());
            }
        }
        if (CollectionUtil.isNotEmpty(contractRemoveList)){
            procurementContractService.deleteLogic(contractRemoveList.stream()
                    .map(ProcurementContract::getId).collect(Collectors.toList()));
        }

        procurementContractService.saveOrUpdateBatch(procurementContractList);
        return PurchaseTransferResultVO.builder().insertIds(insertIds)
                .updateIds(updateIds).successNum(materialProcurementList.size()).build();
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public boolean saveFile(List<MultipartFile> files, List<PurchaseTransferFileDTO> purchaseTransferFileDTOS) {
        if (CollectionUtil.isEmpty(purchaseTransferFileDTOS)){
            return true;
        }
        List<PageData> fileInfoList = FilesUtil.upFiles(files);
        Map<String, PageData> fileMap = fileInfoList.stream().collect(Collectors.toMap(p -> p.getString("md5"), p -> p, (p1, p2) -> p1));
        List<MaterialProcurement> existList = materialProcurementService
                .list(new LambdaQueryWrapper<MaterialProcurement>()
                        .eq(MaterialProcurement::getDataSource, SUN_DATA_SOURCE)
                        .isNotNull(MaterialProcurement::getDataSourceId));
        Map<String, Long> existIdMap =  existList.stream().collect(Collectors
                .toMap(MaterialProcurement::getDataSourceId, MaterialProcurement::getId));
        List<ProcurementContract> existContractList = procurementContractService
                .list(new LambdaQueryWrapper<ProcurementContract>()
                        .eq(ProcurementContract::getDataSource, SUN_DATA_SOURCE)
                        .isNotNull(ProcurementContract::getDataSourceId));
        Map<String, Long> existIdContractMap =  existContractList.stream().collect(Collectors
                .toMap(ProcurementContract::getDataSourceId, ProcurementContract::getId));

        HashMap<String, String> extMap = FilesUtil.extMap();
        List<HashMap> fileList = new ArrayList<>();
        List<String> parentIds = new ArrayList<>();
        for (PurchaseTransferFileDTO purchaseTransferFileDTO : purchaseTransferFileDTOS){
            if (purchaseTransferFileDTO.getType() == 1){
                if (existIdMap.containsKey(purchaseTransferFileDTO.getDataSourceId())){
                    String parentId = String.valueOf(existIdMap.get(purchaseTransferFileDTO.getDataSourceId()));
                    parentIds.add(parentId);
                    setFilePageData(fileMap, extMap, purchaseTransferFileDTO.getFileMD5List(), fileList, parentId);
                }
            }else if (purchaseTransferFileDTO.getType() == 2){
                if (existIdContractMap.containsKey(purchaseTransferFileDTO.getDataSourceId())){
                    String parentId = String.valueOf(existIdContractMap.get(purchaseTransferFileDTO.getDataSourceId()));
                    parentIds.add(parentId);
                    setFilePageData(fileMap, extMap, purchaseTransferFileDTO.getFileMD5List(), fileList, parentId);
                }
            }
        }

        if (CollectionUtil.isNotEmpty(fileList)){
            try {
                fileDao.delByParentIds(parentIds);
                fileDao.saveAll(fileList);
            }catch (Exception e){
                return false;
            }
        }
        return true;
    }

    @Override
    public String ythSubmitBatch(String data) {
        YthResult ythResult = new YthResult();
        //成功的id集合
        List<String> successIds = new ArrayList<>();
        //失败的id集合
        List<String> failIds = new ArrayList<>();
        //失败的原因
        List<String> failReasons = new ArrayList<>();
        List<MaterialProcurement> dataList = JSON.parseArray(data, MaterialProcurement.class);
        if (CollectionUtil.isEmpty(dataList)){
            failReasons.add("数据为空");
            ythResult.setFailReason(StringUtils.join(failReasons, StringPool.COMMA));
            return JSON.toJSONString(ythResult);
        }
        List<MaterialProcurement> existList = materialProcurementService
                .list(new LambdaQueryWrapper<MaterialProcurement>()
                        .eq(MaterialProcurement::getDataSource, YthConstant.DATA_NINGBO)
                        .isNotNull(MaterialProcurement::getDataSourceId));
        Map<String, MaterialProcurement> existMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(existList)){
            existMap = existList.stream().collect(Collectors
                    .toMap(MaterialProcurement::getDataSourceId, materialProcurement -> materialProcurement));
        }

        List<ProcurementContract> existContractList = procurementContractService
                .list(new LambdaQueryWrapper<ProcurementContract>()
                        .eq(ProcurementContract::getDataSource, YthConstant.DATA_NINGBO)
                        .isNotNull(ProcurementContract::getDataSourceId));
        Map<String, ProcurementContract> existContractMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(existContractList)){
            existContractMap = existContractList.stream().collect(Collectors
                    .toMap(ProcurementContract::getDataSourceId, procurementContract -> procurementContract));
        }
        List<Org> orgList = orgService.getYthOrgList();
        Map<String, Org> dataSourceIdOrgMap = orgList.stream().collect(Collectors.toMap(Org::getDataSourceId, Function.identity()));

        List<Long> existIds = new ArrayList<>();
        dataList = dataList.stream()
                .filter(materialProcurement -> StringUtil.isNotBlank(materialProcurement.getDataSourceId())).collect(Collectors.toList());

        for (MaterialProcurement materialProcurement : dataList){
            if (StringUtil.isBlank(materialProcurement.getFillingUnitId())
                    || !dataSourceIdOrgMap.containsKey(String.valueOf(materialProcurement.getFillingUnitId()))){
                failIds.add(materialProcurement.getDataSourceId());
                continue;
            }
            if (existMap.containsKey(materialProcurement.getDataSourceId())){
                materialProcurement.setId(existMap.get(materialProcurement.getDataSourceId()).getId());
                materialProcurement.setCode(existMap.get(materialProcurement.getDataSourceId()).getCode());
                existIds.add(materialProcurement.getId());
            }else {
                materialProcurement.setId(null);
                materialProcurement.setFormType(String.valueOf(FR_MATERIAL_PROCUREMENT_FORM));
                materialProcurement.setCode(formCodeService.getCode(FR_MATERIAL_PROCUREMENT_FORM));
            }
            successIds.add(materialProcurement.getDataSourceId());
            materialProcurement.setFillingUnitId(dataSourceIdOrgMap.get(String.valueOf(materialProcurement.getFillingUnitId())).getId());
            materialProcurement.setCreateCompanyId(materialProcurement.getFillingUnitId());
            materialProcurement.setDataSource(YthConstant.DATA_NINGBO);
            materialProcurement.setStatus(FINISH);
            materialProcurement.setIsDeleted(INIT_DELETED);
            materialProcurementService.saveOrUpdate(materialProcurement);
            if (CollectionUtil.isNotEmpty(materialProcurement.getDecisionDocIds())){
                String tempIds = StringUtil.join(materialProcurement.getDecisionDocIds(), StringPool.COMMA);
                fileService.upYthFile(tempIds, String.valueOf(materialProcurement.getId()));
            }else {
                fileService.upYthFile(null, String.valueOf(materialProcurement.getId()));
            }
        }

        materialProcurementService.saveOrUpdateBatch(dataList);

        List<ProcurementContract> procurementContractList = new ArrayList<>();
        List<ProcurementContract> contractRemoveList = new ArrayList<>();
        contractRemoveList.addAll(existContractList);
        for (MaterialProcurement materialProcurement : dataList){
            if (CollectionUtil.isNotEmpty(materialProcurement.getProcurementContracts())){
                for (ProcurementContract procurementContract : materialProcurement.getProcurementContracts()){
                    procurementContract.setMaterialProcurementId(materialProcurement.getId());
                    procurementContract.setDataSource(YthConstant.DATA_NINGBO);
                    procurementContract.setIsDeleted(INIT_DELETED);
                    if (existContractMap.containsKey(procurementContract.getDataSourceId())){
                        procurementContract.setId(existContractMap.get(procurementContract.getDataSourceId()).getId());
                        contractRemoveList.remove(existContractMap.get(procurementContract.getDataSourceId()));
                    }
                }
                procurementContractList.addAll(materialProcurement.getProcurementContracts());
            }
        }
        if (CollectionUtil.isNotEmpty(contractRemoveList)){
            procurementContractService.deleteLogic(contractRemoveList.stream()
                    .map(ProcurementContract::getId).collect(Collectors.toList()));
        }

        procurementContractService.saveOrUpdateBatch(procurementContractList);
        for (ProcurementContract procurementContract : procurementContractList){
            if (CollectionUtil.isNotEmpty(procurementContract.getContractDocIds())){
                String tempIds = StringUtil.join(procurementContract.getContractDocIds(), StringPool.COMMA);
                fileService.upYthFile(tempIds, String.valueOf(procurementContract.getId()));
            }else {
                fileService.upYthFile(null, String.valueOf(procurementContract.getId()));
            }
        }

        ythResult.setSuccessIds(successIds);
        ythResult.setFailIds(failIds);
        ythResult.setFailReason(StringUtils.join(failReasons, StringPool.COMMA));
        //ythResult转换成json字符串
        return JSON.toJSONString(ythResult);
    }

    private void setFilePageData(Map<String, PageData> fileMap,  HashMap<String, String> extMap, List<String> md5List,
                                 List<HashMap> fileList, String id){
        for (String str : md5List){
            if (fileMap.containsKey(str)){
                PageData pd = fileMap.get(str);
                PageData fileInfoMap = fileService.fileToFileInfo(pd);
                fileInfoMap.put("parentId", id);
                String ext = fileInfoMap.getString("ext");
                if (extMap.containsKey(ext)){
                    fileInfoMap.put("mime", extMap.get(ext));
                }
                fileList.add(fileInfoMap);
            }
        }
    }

}
